#include "vcd-get-login-ticket.h"
#include "vcd-refresh-vm-info.h"
#include "vcd-vm-connect.h"
#include "vcd-get-vm-info.h"
#include "vcd-conf/vcd-conf.h"
#include "vcd-json-parser.h"
#include "vcd-common.h"
#include "vcd-linux-ui/vcd-message-dialog.h"
#include "vcd-linux-ui/vcd-logined-window.h"
#include "vcd-util.h"
#include "vcd-linux-ui/vcd-start-window.h"
#include "vcd-new-login-mode.h"

char g_new_resources_ticket[1024] = {0};
char g_final_ticket[1024] = {0};
char g_token[512] = {0};
//uint64_t g_last_fresh_ticket_time = 0;

static void check_user_name_suffix(char* user_name);
static gboolean get_new_api_ticket_callback_task(gpointer data);
static void fill_free_ticket_param(ticket_param * tp);
static gboolean get_ticket_callback_task(gpointer data);

/*
 * 在pve中@pam表示管理员用户名后缀，@pve表示普通用户名后缀，
 * 但是普通用户输入的时候不可能去输入@pve所以我们需要在代码中自己加入@pve，
 * 但是如果用户自己已经输入了@pve或者@pam我们就不需要做修改了
 * 如果用户名中有@就不能做操作了，因为@有可能是域账户
*/
static void check_user_name_suffix(char* user_name)
{
    if(ends_with(user_name, "@pam") ||
           ends_with(user_name, "@pve") ||
               strstr(user_name, "@")) {
        return;
    }
    strcat(user_name, "@pve");
}

static
gboolean get_new_api_ticket_callback_task(gpointer data)
{
    JsonObject *obj1 = NULL;
    JsonObject *obj2 = NULL;
    gboolean bres = FALSE;
    JsonParser *parser = NULL;
    JsonNode *node1 = NULL;

    if (data == NULL) {
        LOG_ERROR("data = NULL");
        goto fail;
    }

    struct network_response* res = (struct network_response*)data;
    char *memory = res->memory;
    if (!memory) {
        message_box(" 连接失败（请检查网络或节点）！ ");//网络错误或者节点有错
        goto fail;
    }

    parser = json_parser_new();
    if (parser == NULL) {
        LOG_ERROR("json_parser_new fail");
        goto fail;
    }
    bres = json_parser_load_from_data(parser, memory, -1, NULL);//json数据格式：{"data":{obj,obj {obj,obj} , {obj,obj}}}
    if (!bres) {
        LOG_ERROR("json_parser_load_from_data fail, data:%s", memory);
        goto fail;
    }

    node1 = json_parser_get_root(parser);//得到节点
    if (node1 == NULL) {
        LOG_ERROR("node = NULL");
        goto fail;
    }

    obj1 = json_node_get_object(node1);//得到节点内的对象
    if (obj1 == NULL) {
        LOG_ERROR("obj = NULL");
        goto fail;
    }

    obj2 = json_object_get_object_member(obj1, "data");//得到obj1对象data内嵌套的对象
    if (obj2 == NULL) {//网络连接上但是这里没获取到东西，说明是用户名和密码有问题
        LOG_ERROR("username or passwd error");
        message_box("        用户名或密码错误！        ");
        goto fail;
    }

    memset(g_new_resources_ticket, 0, sizeof(g_new_resources_ticket));
    sprintf(g_new_resources_ticket, "cookie:PVEAuthCookie=%s;PHPSESSID=%s", 
                                     json_object_get_string_member(obj2, "ticket"), 
                                     json_object_get_string_member(obj2, "PHPSESSID"));

    M_DEBUG("g_new_resources_ticket: %s", g_new_resources_ticket);

    main_logined_window(FALSE);

fail:
    stop_login_button_state();
    if(parser){
        g_object_unref(parser);
    }
    network_response_free(&res);
    return FALSE;
}

static void fill_free_ticket_param(ticket_param * tp)
{
    g_return_if_fail(tp != NULL);

    if (tp->ticket)
        snprintf(g_final_ticket,sizeof(g_final_ticket),"cookie:PVEAuthCookie=%s", tp->ticket);

    if (tp->token)
        snprintf(g_token, sizeof(g_token),"CSRFPreventionToken:%s", tp->token);

    M_DEBUG("ticket: %s\n token:%s", g_final_ticket, g_token);

    G_SAFE_FREE(tp->ticket);
    G_SAFE_FREE(tp->token);
}

static gboolean get_ticket_callback_task(gpointer data)
{
    int ret = 0;
    struct vcd_conf* tmp_vcd_conf = g_vcd_conf;
    ticket_param  tp;
    ticket_context *ctx = NULL;
    struct network_response* res = (struct network_response*)data;

    if (data == NULL) {
        goto fail;
    }

    ctx = (ticket_context*)res->data_priv;

    char *memory = res->memory;
    if (!memory) {
        message_box(" 连接失败（请检查网络或节点）！ ");
        goto fail;
    }

    if (res->error_msg != NULL) {
        LOG_ERROR("curl get error message = %s", res->error_msg);
        message_box(res->error_msg);
        goto fail;
    }

    memset(&tp, 0, sizeof(ticket_param));
    ret = json_parser_get_ticket(memory, &tp);
    if (ret != 0)  
        goto fail;

    fill_free_ticket_param(&tp);

    if (ctx->action == ACTION_FRESH_TICKET) {
        M_DEBUG("ctx->action == ACTION_FRESH_TICKET");
        goto fail;
    }

    if (EMODE_NEW == tmp_vcd_conf->login_mode) {
        char user_name[50] = {0};
        strncpy(user_name, tmp_vcd_conf->username, sizeof(user_name));
        check_user_name_suffix(user_name);
        struct network_request_arg *network_task = (struct network_request_arg *)malloc(sizeof(struct network_request_arg));
        network_task->timeout = 3L;
        network_task->list = NULL;
        network_task->data_priv = NULL;
        network_task->callback = get_new_api_ticket_callback_task;
        network_task->http_method = CURLOPT_POST;
        sprintf(network_task->post_fields, "username=%s&password=%s", user_name, tmp_vcd_conf->plaintext_passwd);
        sprintf(network_task->url, "https://%s/api/user/pveLogin", get_ip_port());

        net_req_list_add(network_task);
    } else {
        G_SAFE_FREE(ctx);
        network_response_free(&res);

        stop_login_button_state();
        main_logined_window(FALSE);
        return FALSE;
    }

fail:
    if( ctx && ctx->action == ACTINON_LOGIN){
        stop_login_button_state();
    }
    G_SAFE_FREE(ctx);
    network_response_free(&res);
    return FALSE;
}

int start_get_ticket(TICKET_ACTION action)
{
    ticket_context *ctx = (ticket_context*)g_malloc0(sizeof(ticket_context));
    g_return_val_if_fail(ctx != NULL, -1);

    ctx->action = action;
    //g_last_fresh_ticket_time = get_time();

    struct network_request_arg *req = g_malloc0(sizeof(struct network_request_arg));
    if (req == NULL) {
        LOG_ERROR("malloc network_req_arg error");
        G_SAFE_FREE(ctx);
        return -1;
    }

    struct vcd_conf* cf = g_vcd_conf;

    char user_name[50] = {0};
    strncpy(user_name, cf->username, sizeof(user_name));
    check_user_name_suffix(user_name);

    /*填充任务需要参数*/
    if (PRIVATE_LOGIN == cf->login_way) {
        /*老的ticket获取方法*/
        snprintf(req->post_fields,sizeof(req->post_fields), "username=%s&password=%s",
                 user_name, cf->plaintext_passwd);

        snprintf(req->url, sizeof(req->url), "https://%s/api2/json/access/ticket", get_ip_port());

        /*创建任务队列成员*/
        req->timeout = 5L;
        req->list = NULL;
        req->data_priv = (gpointer)ctx;
        req->http_method = CURLOPT_POST;
        req->callback = get_ticket_callback_task;

        net_req_list_add(req);
    } else {
        //     encode(txt_passwd);

        //     strcpy(get_ticket_info.url, "https://api3.verycloud.cn/API/OAuth/authorize");

        //     strcpy(get_ticket_info.post_fields, "{\"username\":\"");
        //     strcat(get_ticket_info.post_fields, g_txt_user);
        //     strcat(get_ticket_info.post_fields, "\",\"password\":\"");
        //     strcat(get_ticket_info.post_fields, txt_passwd);
        //     strcat(get_ticket_info.post_fields, "\"}");

        //     if (!get_public_login_token()) {
        //         return;
        //     }
        //     public_login_main_dialog();
    }

    if(action == ACTINON_LOGIN){
        start_login_button_state();
    }
    return 0;
}
